# coding:utf-8

import os  # 导入操作系统接口模块
import sys  # 导入系统相关功能模块
from empty import Empty  # 导入基础Flask应用框架

{%- if cookiecutter.use_http_mixin in ('yes', 'y') %}
# 如果启用了HTTP混合功能，导入HttpMixin
from mixins import HttpMixin
{% endif %}

{%- if cookiecutter.json_friendly in ('yes', 'y') %}
try:
    import __builtin__  # Python2兼容
except ImportError:
    import builtins as __builtin__  # Python3兼容

# 创建全局别名，使JSON中的true/false/null可直接在Python中使用
__builtin__.true = True
__builtin__.false = False
__builtin__.null = None
{% endif %}

# 定义应用类的基类列表
base_cls_list = [Empty]  # 初始包含基础Empty类

{%- if cookiecutter.use_http_mixin in ('yes', 'y') %}
# 如果启用了HTTP混合功能，将HttpMixin添加到基类列表开头
base_cls_list = [HttpMixin] + base_cls_list
{% endif %}

# 设置项目路径和蓝图应用路径
PROJECT_PATH = os.path.abspath(os.path.dirname(__file__))  # 获取项目根目录
sys.path.insert(0, os.path.join(PROJECT_PATH, "apps"))  # 将蓝图应用目录添加到Python路径

# 兼容Python2和Python3的basestring类型
basestring = getattr(__builtins__, 'basestring', str)


# 动态创建应用类
App = type('App', tuple(base_cls_list), {})  # 使用元类创建组合基类的新类


def config_str_to_obj(cfg):
    """
    将字符串形式的配置名转换为实际的配置对象
    
    参数:
        cfg: 可以是字符串（配置类名）或配置对象本身
    """
    if isinstance(cfg, basestring):
        # 动态导入配置模块并获取指定配置类
        module = __import__('config', fromlist=[cfg])
        return getattr(module, cfg)
    return cfg  # 如果已经是配置对象则直接返回


def app_factory(config, app_name, blueprints=None):
    """
    应用工厂函数，创建并配置Flask应用实例
    
    参数:
        config: 配置对象或配置类名字符串
        app_name: 应用名称
        blueprints: 蓝图列表（可选）
    """
    from commands import new_app, test_cmd  # 导入自定义命令

    # 创建应用实例，设置模板文件夹路径
    app = App(app_name, template_folder=os.path.join(PROJECT_PATH, 'templates'))
    
    # 转换配置参数为配置对象
    config = config_str_to_obj(config)

    # 添加自定义CLI命令
    app.cli.add_command(new_app)  # 添加创建新蓝图命令
    app.cli.add_command(test_cmd)  # 添加运行测试命令

    # 配置应用
    app.configure(config)  # 应用配置
    app.add_blueprint_list(blueprints or config.BLUEPRINTS)  # 添加蓝图
    app.setup()  # 执行应用设置

    return app  # 返回配置好的应用实例


def heroku():
    """
    Heroku部署专用函数
    从配置模块导入默认配置和项目名称
    """
    from config import Config, project_name  # 导入默认配置和项目名称
    # 创建并返回配置好的应用实例
    return app_factory(Config, project_name)